package com.lightsaber.trade.core.service.account.impl;

import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

public class AccessDecisionManagerImpl implements AccessDecisionManager {

    private final static Logger LOG = LoggerFactory.getLogger(AccessDecisionManagerImpl.class);

    // In this method, need to compare authentication with configAttributes.
    // 1, A object is a URL, a filter was find permission configuration by this
    // URL, and pass to here.
    // 2, Check authentication has attribute in permission configuration
    // (configAttributes)
    // 3, If not match corresponding authentication, throw a
    // AccessDeniedException.
    @Override
    public void decide(final Authentication authentication, final Object object,
            final Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,
            InsufficientAuthenticationException {
        if (configAttributes == null) {
            return;
        }
        LOG.info(object.toString()); // object is a URL.
        Iterator<ConfigAttribute> ite = configAttributes.iterator();
        while (ite.hasNext()) {
            ConfigAttribute ca = ite.next();
            String needRole = ((SecurityConfig) ca).getAttribute();
            if (haveRole(authentication, needRole)) {
                return;
            }
        }
        throw new AccessDeniedException("no right");
    }

    private boolean haveRole(final Authentication authentication, final String needRole) {
        for (GrantedAuthority ga : authentication.getAuthorities()) {
            if (needRole.equals(ga.getAuthority())) { // ga is user's role.
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean supports(final ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(final Class<?> clazz) {
        return true;
    }

}
